/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package spaceinvaders;

import Util.Botao;
import Util.Drawable;
import Util.ImageReader;
import Util.Nave;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

/**
 * Painel de desenhos do jogo
 * @author Lucas-PC
 */
public class Graficos extends JPanel {

    public static final int stateIntro = 0;
    public static final int stateJogo = 1;
    public static final int stateRecorde = 2;
    public static final int statePerdeu = 3;
    public static final int stateGanhou = 4;
    //Desenhista d;
    //Elementos que devem ser desenhados
    ArrayList<Drawable> desenhos;
    //Plano de fundo atual do jogo
    Image bg;
    //Planos de fundo do jogo
    Image[] bgs = new Image[3];
    //Imagem cinza e transparente para pausar o jogo
    Image pause;
    //Botões
    Botao bIniciar, bRecorde, bVoltar, bVoltar2, bContinuar;
    //Strings para serem desnhadas na tela: frames por segundo, pontuação e vidas do jogador
    String fps, sPontos, sVidas;
    //Fontes para se definir como as strings serão desenhadas
    Font fGeral, fRec;
    //Nomes dos recordistas do jogo
    String[] recordes;
    //Pontos deles
    int[] pontos;
    //Ponto para verificar a posição do mouse
    Point p;
    //Parte funcional
    Func fu;
    //Nave que o jogador controla
    Nave nave;
    //Strings para a tela de vitória e a pontuação do jogador
    String ganhou1, ganhou2, pontuacao;

    public Graficos(ArrayList<Drawable> desenhos, Func func) {
        fu = func;
        nave = fu.getNave();

        this.desenhos = desenhos;
        //d = new Desenhista(desenhos, this);
        bgs[0] = ImageReader.read("/Imagens/Intro.jpg");
        bgs[1] = ImageReader.read("/Imagens/Campo.jpg");
        bgs[2] = ImageReader.read("/Imagens/end.jpg");
        bg = bgs[0];
        pause = ImageReader.read("/Imagens/Pause.png");
        fGeral = new Font("Arial", Font.PLAIN, 16);
        fRec = new Font("Arial", Font.PLAIN, 40);

        ganhou1 = "Parabéns, você ganhou";
        ganhou2 = "o jogo!";

        //<editor-fold defaultstate="collapsed" desc="Botões">
        bIniciar = new Botao("Iniciar", 278, 330, this);
        bRecorde = new Botao("Recordes", 266, 380, this);
        bVoltar = new Botao("Voltar", 541, 446, this);
        bVoltar2 = new Botao("Voltar", 277, 260, this);
        bContinuar = new Botao("Continuar", 256, 220, this);

        bIniciar.setVisible(true);
        this.desenhos.add(bIniciar);
        bRecorde.setVisible(true);
        this.desenhos.add(bRecorde);
        bVoltar.setVisible(false);
        this.desenhos.add(bVoltar);
        bVoltar2.setVisible(false);
        this.desenhos.add(bVoltar2);
        bContinuar.setVisible(false);
        this.desenhos.add(bContinuar);

        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                p = e.getPoint();
                //Dependendo da posição do mouse no momento de clique, inicia um dos estados do jogo
                if (bIniciar.isVisible() && bIniciar.getRect().contains(p)) {
                    fu.initJogo();
                    initJogo();
                } else if (bRecorde.isVisible() && bRecorde.getRect().contains(p)) {
                    fu.initRecorde();
                    initRecorde();
                } else if (bVoltar.isVisible() && bVoltar.getRect().contains(p)) {
                    fu.initIntro();
                    initIntro();
                } else if (bVoltar2.isVisible() && bVoltar2.getRect().contains(p)) {
                    fu.initIntro();
                    initIntro();
                } else if (bContinuar.isVisible() && bContinuar.getRect().contains(p)) {
                    fu.setPaused(false);
                }
            }
        });
        //</editor-fold>
        setFocusable(true);
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (fu.getState() == stateJogo) {
                    //Se o usuário pressiona a tecla ESC, pausa/despausa o jogo
                    if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
                        fu.setPaused(!fu.getPaused());
                    }
                    if (!fu.getPaused()) {
                        //Se o usuário pressiona a tecla direcional esquerda, move para a esquerda
                        if (e.getKeyCode() == KeyEvent.VK_LEFT) {
                            nave.setMovimento(-1);
                        //Se foi a direcional direita, move para a direita
                        } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
                            nave.setMovimento(1);
                        }
                        //Se pressionou a tecla X, atira
                        if (e.getKeyCode() == KeyEvent.VK_X) {
                            if (!nave.getAtirou()) {
                                nave.atirar();
                            }
                        }
                    }
                }
            }

            @Override
            public void keyReleased(KeyEvent e) {
                //Se o usuário soltou uma das teclas direcionais, para o movimento
                if (e.getKeyCode() == KeyEvent.VK_LEFT || e.getKeyCode() == KeyEvent.VK_RIGHT) {
                    nave.setMovimento(0);
                }
                //Se o usuário soltou a tecla X, permite que ele atire de novo
                if (e.getKeyCode() == KeyEvent.VK_X) {
                    nave.setAtirou(false);
                }
            }
        });
    }

    //<editor-fold defaultstate="collapsed" desc="Estados">
    public void initJogo() {
        bIniciar.setVisible(false);
        bRecorde.setVisible(false);
        bVoltar.setVisible(false);
        bVoltar2.setVisible(false);
        bContinuar.setVisible(false);
        bg = bgs[stateJogo];
    }

    public void initRecorde() {
        bIniciar.setVisible(false);
        bRecorde.setVisible(false);
        bVoltar.setVisible(true);
        bg = bgs[stateRecorde];
    }

    public void initIntro() {
        bIniciar.setVisible(true);
        bRecorde.setVisible(true);
        bVoltar.setVisible(false);
        bVoltar2.setVisible(false);
        bContinuar.setVisible(false);
        bg = bgs[stateIntro];
    }

    public void initPerdeu() {
        bVoltar.setVisible(true);
        bg = bgs[stateRecorde];
    }

    public void initGanhou() {
        bVoltar.setVisible(true);
        bg = bgs[stateRecorde];
    }
    //</editor-fold>

    //Se o jogador fez uma pontuação maior que a menor salva, pede o nome dele e o insere ordenadamente nos recordes
    public void checarRecorde(int pontuacao) {
        if (pontuacao > pontos[9]) {
            int i;
            String nome;
            do {
                nome = JOptionPane.showInputDialog(this, "Digite seu nome:", "Novo recorde!", JOptionPane.PLAIN_MESSAGE);
            } while (nome == null || nome.equals(""));
            for (i = 9; i > 0 && pontuacao > pontos[i - 1]; i--) {
                recordes[i] = recordes[i - 1];
                pontos[i] = pontos[i - 1];
            }
            recordes[i] = nome;
            pontos[i] = pontuacao;
        }
    }

    public int[] getPontos() {
        return pontos;
    }

    public String[] getRecordes() {
        return recordes;
    }

    public void setRecordes(String[] recordes, int[] pontos) {
        this.recordes = recordes;
        this.pontos = pontos;
    }

    @Override
    public void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;

        g2d.setFont(fGeral);
        g2d.setColor(Color.WHITE);
        //Desenha o plano de fundo
        g2d.drawImage(bg, 0, 0, this);
        //Desenha a quantidade de frames por segundo do jogo
        g2d.drawString("Frames: " + fps, 0, 16);

        //Desenha os objetos do jogo
        Object[] des = desenhos.toArray();
        for (Object o : des) {
            Drawable d = (Drawable) o;
            if (d != null) {
                d.draw(g2d, this);
            }
        }

        switch (fu.getState()) {
            //Se está na tela de recordes, escreve os nomes e pontos dos recordistas
            case stateRecorde:
                g2d.setFont(fRec);
                for (int i = 0; i < 10; i++) {
                    g2d.drawString(recordes[i], 300 - g2d.getFontMetrics().stringWidth(recordes[i]), 50 + i * 40);
                    g2d.drawString(Integer.toString(pontos[i]), 340, 50 + i * 40);
                }
                break;

            case stateJogo:
                //Escreve a pontuação
                sPontos = "Pontuação: " + Integer.toString(fu.getPontos());
                g2d.drawString(sPontos, 280, 16);
                //Escreve as vidas do jogador
                sVidas = "Vidas: " + Integer.toString(fu.getVidas());
                g2d.drawString(sVidas, 570, 16);
                //Se o jogo estiver pausado, desenha a imagem cinza e os botões de continuar e voltar
                if (fu.getPaused()) {
                    g2d.drawImage(pause, 0, 0, null);
                    bVoltar2.setVisible(true);
                    bContinuar.setVisible(true);
                } else {
                    bVoltar2.setVisible(false);
                    bContinuar.setVisible(false);
                }
                break;

            //Escreve o texto na tela e a pontuação do jogador
            case stateGanhou:
                g2d.setFont(fRec);
                g2d.drawString(ganhou1, 105, 100);
                g2d.drawString(ganhou2, 259, 140);
                pontuacao = "Sua pontuação: " + fu.getPontos();
                g2d.drawString(pontuacao, 320 - g2d.getFontMetrics().stringWidth(pontuacao) / 2, 200);
                bVoltar2.setVisible(false);
                break;
                
            case statePerdeu:
                g2d.setFont(fRec);
                g2d.drawString("Você perdeu O Jogo", 139, 130);
                pontuacao = "Sua pontuação: " + fu.getPontos();
                g2d.drawString(pontuacao, 320 - g2d.getFontMetrics().stringWidth(pontuacao) / 2, 200);
                break;
        }

    }

//    class Desenhista extends Thread {
//
//        ArrayList<Drawable> desenhos = null;
//        Graphics2D g = null;
//        JPanel jp = null;
//
//        public Desenhista(ArrayList<Drawable> desenhos, JPanel jp) {
//            this.desenhos = desenhos;
//            this.jp = jp;
//        }
//
//        @Override
//        public void run() {
//            while (true) {
//                g = (Graphics2D) jp.getGraphics();
//                if (desenhos != null && g != null && jp != null) {
//                    g.setFont(fGeral);
//                    g.setColor(Color.WHITE);
//                    g.drawString("Frames: " + fps, 0, 16);
//                    g.drawImage(bg, 0, 0, jp);
//
//                    sPontos = "Pontuação: " + Integer.toString(fu.getPontos());
//                    g.drawString(sPontos, 280, 16);
//                    sVidas = "Vidas: " + Integer.toString(fu.getVidas());
//                    g.drawString(sVidas, 570, 16);
//                    if (fu.getPaused()) {
//                        g.drawImage(pause, 0, 0, null);
//                        bContinuar.setVisible(true);
//                        bVoltar2.setVisible(true);
//                    }
//
//                    if (fu.getState() == stateRecorde) {
//                        g.setFont(fRec);
//                        for (int i = 0; i < 10; i++) {
//                            g.drawString(recordes[i], 280, 50 + i * 40);
//                        }
//                    }
//
//                    for (Drawable d : desenhos) {
//                        if (d != null) {
//                            d.draw(g, jp);
//                        }
//                    }
//                }
//            }
//        }
//    }
    //Define a quantos frames por segundo o jogo está rodando
    public void setFPS(long fps) {
        this.fps = Long.toString(fps);
    }
}
